home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / mus / play / tracker_3_19.lzh / tracker / main.c < prev    next >
C/C++ Source or Header  |  1993-11-17  |  12KB  |  456 lines

  1. /* main.c */
  2.  
  3. /* plays sound/noisetracker files on Sparc, silicon graphics.
  4.  * Authors  : Liam Corner - zenith@dcs.warwick.ac.uk
  5.  *            Marc Espie - espie@ens.fr
  6.  *            Steve Haehnichen - shaehnic@ucsd.edu
  7.  *            Andrew Leahy - alf@st.nepean.uws.edu.au
  8.  *
  9.  * Usage    : tracker <filename> 
  10.  *  this version plays compressed files as well.
  11.  */
  12.  
  13. /* $Id: main.c,v 3.17 1993/11/17 15:31:16 espie Exp espie $
  14.  * $Log: main.c,v $
  15.  * Revision 3.17  1993/11/17  15:31:16  espie
  16.  * New version.
  17.  *
  18.  * Revision 3.16  1993/11/11  20:00:03  espie
  19.  * Amiga support.
  20.  *
  21.  * Revision 3.15  1993/08/04  11:55:21  espie
  22.  * Fixed upo previous song bug.
  23.  *
  24.  * Revision 3.13  1993/07/18  10:39:44  espie
  25.  * Added forking under unix. Experimental...
  26.  *
  27.  * Revision 3.11  1993/05/09  14:06:03  espie
  28.  * Fixed up bug with mix option no longer working.
  29.  *
  30.  * Revision 3.10  1993/04/25  15:13:36  espie
  31.  * Force new version.
  32.  *
  33.  * Revision 3.9  1993/01/15  14:00:28  espie
  34.  * Added bg/fg test.
  35.  *
  36.  * Revision 3.7  1992/12/03  15:00:50  espie
  37.  * restore stty.
  38.  *
  39.  * Revision 3.5  1992/11/24  10:51:19  espie
  40.  * Added loads of new options.
  41.  *
  42.  * Revision 3.3  1992/11/22  17:20:01  espie
  43.  * Augmented usage.
  44.  *
  45.  * Revision 3.2  1992/11/20  14:53:32  espie
  46.  * Added finetune.
  47.  *
  48.  * Revision 3.1  1992/11/19  20:44:47  espie
  49.  * Protracker commands.
  50.  *
  51.  * Revision 3.0  1992/11/18  16:08:05  espie
  52.  * New release.
  53.  *
  54.  * Revision 2.20  1992/11/17  17:06:25  espie
  55.  * Added PREVIOUS_SONG handling ???
  56.  * Use streamio for new interface (obsolescent signal handlers), and
  57.  * related changes.
  58.  * Cleaned up path reader, and better signal handling.
  59.  * Support for open_file.
  60.  * Added imask.
  61.  * Use transparent decompression/path lookup through open_file/close_file.
  62.  * Added setup_audio().
  63.  * Added some frequency/oversample/stereo change on the fly.
  64.  * Necessitates rightful closing/reopening of audio.
  65.  * Added compression methods. Changed getopt.
  66.  * Separated mix/stereo stuff.
  67.  * Added transpose feature.
  68.  * Added possibility to get back to MONO for the sgi.
  69.  * Added stereo capabilities to the indigo version.
  70.  * Added recovery and reread for automatic recognition
  71.  * of old/new tracker files.
  72.  * Added two level of fault tolerancy.
  73.  * Added more rational options.
  74.  * Moved almost everything to audio and automaton.
  75.  * Structured part of the code, especially replay ``automaton''
  76.  * and setting up of effects.
  77.  *
  78.  * Revision 1.26  1991/11/17  17:09:53  espie
  79.  * Added missing prototypes.
  80.  * Some more info while loading files.
  81.  * Added FAULT env variable, FAULT resistant playing,
  82.  * for playing modules which are not quite correct.
  83.  * Serious bug: dochangespeed was not reset all the time.
  84.  * Check all these parameters, they MUST be reset for
  85.  * each new song.
  86.  * Fixed a stupid bug: when env variable LOOPING was
  87.  * undefined, we got a segv on strcmp.
  88.  * Now we just test for its existence, since this is
  89.  * about all we want...
  90.  * Bug correction: when doing arpeggio, there might not
  91.  * be a new note, so we have to save the old note value
  92.  * and do the arppeggio on that note.
  93.  * Completely added control with OVERSAMPLE and FREQUENCY.
  94.  * Added control flow.
  95.  * Added pipe decompression, so that now you can do
  96.  * str32 file.Z directly.
  97.  * stdin may go away.
  98.  * Added arpeggio.
  99.  * Added vibslide and portaslide.
  100.  * Added speed command.
  101.  * Added signal control.
  102.  * Error checking: there shouldn't be that many
  103.  * segv signals any more.
  104.  * Moved every command to commands.c.
  105.  * Added some debug code for showing the full
  106.  * sequence for a file.
  107.  * Corrected the bug in volume slide: there is
  108.  * no default value, i.e., if it is 0, it is 0,
  109.  * as stupid as it may seem.
  110.  * Added vibrato.
  111.  * Added fastskip/corrected skip.
  112.  * Modified control flow of the player till
  113.  * it looks like something reasonable (i.e.,
  114.  * the structure is more natural and reflects
  115.  * the way stuff is played actually...)
  116.  * Do not restart the sound when we change instruments
  117.  * on the fly. A bit strange, but it works that way.
  118.  * Modified main to use new data structures.
  119.  * The sound player is MUCH cleaner, it uses now
  120.  * a 3-state automaton for each voice.
  121.  * Corrected ruckus with data type of sample.
  122.  */
  123.      
  124.  
  125. #include <stdio.h>
  126. #include <signal.h>
  127. #include <stdlib.h>
  128. #include <string.h>
  129. #ifndef AMIGA
  130. #include <malloc.h>
  131. #endif
  132.      
  133. #include "defs.h"
  134. #include "extern.h"
  135. #include "song.h"
  136. #include "pref.h"
  137.      
  138. #include "getopt.h"
  139.      
  140. LOCAL char *id = "$Id: main.c,v 3.17 1993/11/17 15:31:16 espie Exp espie $";
  141.  
  142. int pid = 0;
  143. int forked = FALSE;
  144.  
  145. #define USAGE \
  146. "[options] filename [...]\n\
  147. -help               Display usage information\n\
  148. -quiet              Print no output other than errors\n\
  149. -picky              Do not tolerate any faults (default is to ignore most)\n\
  150. -tolerant           Ignore all faults\n\
  151. -mono               Select single audio channel output\n\
  152. -stereo             Select dual audio channel output\n\
  153. -verbose            Show text representation of song\n\
  154. -repeats <count>    Number of repeats (0 is forever) (default 1)\n\
  155. -speed <speed>      Song speed.  Some songs want 60 (default 50)\n\
  156. -mix <percent>      Percent of channel mixing. (0 = spatial, 100 = mono)\n\
  157. -new -old -both     Select default reading type (default is -both)\n\
  158. -frequency <freq>   Set playback frequency in Hz\n\
  159. -oversample <times> Set oversampling factor\n\
  160. -transpose <n>      Transpose all notes up\n\
  161. -show               Show what's going on\n\
  162. -sync               Try to synch audio output with display\n\
  163. \n\
  164. RunTime:\n\
  165. r       restart current song\n\
  166. e,x     exit program\n\
  167. n       next song\n\
  168. p       previous song (experimental)\n\
  169. >       fast forward\n\
  170. <       rewind\n\
  171. S       NTSC tempo\t s\tPAL tempo\n"
  172.  
  173. /* Command-line options. */
  174. LOCAL struct long_option long_options[] =
  175. {
  176.   {"help",              0, 'H'},
  177.   {"quiet",             0, 'Q'}, 
  178.   {"picky",             0, 'P'},
  179.   {"tolerant",          0, 'L'},
  180.   {"new",               0, 'N'},
  181.   {"old",               0, 'O'},
  182.   {"both",              0, 'B'},
  183.   {"mono",              0, 'M'},
  184.   {"stereo",            0, 'S'},
  185.   {"verbose",           0, 'V'},
  186.   {"frequency",         1, 'f'},
  187.   {"oversample",        1, 'o'},
  188.   {"transpose",         1, 't'},
  189.   {"repeats",           1, 'r'},
  190.   {"speed",             1, 's'},
  191.   {"mix",               1, 'm'},
  192.   {"start",             1, 'X'},
  193.   {"cut",               1, '-'},
  194.   {"add",               1, '+'},
  195.   {"show",              0, 'v'},
  196.   {"sync",              0, '='},
  197.   {0,                   0,  0 }
  198. };
  199.  
  200.  
  201. /* global variable to catch various types of errors
  202.  * and achieve the desired flow of control
  203.  */
  204. int error;
  205.  
  206. LOCAL int optvalue(def)
  207. int def;
  208.     {
  209.     int d;
  210.         if (sscanf(optarg, "%d", &d) == 1)
  211.             return d;
  212.         else
  213.             {
  214.             optind--;
  215.             return def;
  216.             }
  217.     }
  218.  
  219. void end_all()
  220.     {
  221.     if (run_in_fg())
  222.         printf("\n");
  223.     do_close_audio();
  224.     sane_tty();
  225.     exit(0);
  226.     }
  227.  
  228. LOCAL struct song *do_read_song(name, type)
  229. char *name;
  230. int type;
  231.     {
  232.     struct song *song;
  233.     FILE *file;
  234.  
  235.     if (run_in_fg())
  236.         fflush(stdout); 
  237.  
  238.     file = open_file(name, "r", getenv("MODPATH"));
  239.     if (!file)
  240.         return NULL;
  241.     song = read_song(file, type); 
  242.     close_file(file);
  243.     return song;
  244.     }
  245.  
  246. int main(argc, argv)
  247. int argc;
  248. char **argv;
  249.     {
  250.     int ask_freq;
  251.     int oversample;
  252.     int stereo;
  253.     int start;
  254.     int transpose;
  255.  
  256.  
  257.     struct pref pref;
  258.     struct song *song;
  259.     BOOL *is_song;
  260.     int c;
  261.     int i;
  262.     int default_type;
  263.  
  264.  
  265.     is_song = (BOOL *)malloc(sizeof(BOOL) * argc);
  266.     if (!is_song)
  267.         end_all();
  268.  
  269.     for (i = 0; i < argc; i++)
  270.         is_song[i] = FALSE;            /* For termination */
  271.  
  272.     start = 0;
  273.     pref.imask = 0;
  274.     pref.bcdvol = 0;
  275.     pref.dump_song = FALSE;
  276.     show = FALSE;
  277.     pref.sync = FALSE;
  278.  
  279.  
  280.     if (argc == 1)
  281.         {
  282.         fprintf(stderr, "Usage: %s %s", argv[0], USAGE);
  283.         end_all();
  284.         }
  285.  
  286.     ask_freq = read_env("FREQUENCY", 0);
  287.     oversample = read_env("OVERSAMPLE", 1);
  288.     transpose = read_env("TRANSPOSE", 0);
  289.     stereo = !getenv("MONO");
  290.     set_mix(30);
  291.  
  292.     create_notes_table();
  293.  
  294.         /* check the command name for default reading type */
  295.  
  296.     default_type = BOTH;
  297.  
  298.     pref.type = default_type;
  299.     pref.repeats = 1;
  300.     pref.speed = 50;
  301.     pref.tolerate = 1;
  302.  
  303.     for (optind = 1; optind < argc; optind++)
  304.         {
  305.         while ((c = getopt(argc, argv, long_options))
  306.                 != EOF)
  307.             switch(c)
  308.                 {
  309.             case '-':
  310.                 if (strcmp(optarg, "all") == 0)
  311.                     pref.imask = ~0;
  312.                 else
  313.                     pref.imask |= 1L << optvalue(0);
  314.                 break;
  315.             case '+':
  316.                 if (strcmp(optarg, "all") == 0)
  317.                     pref.imask = 0;
  318.                 else
  319.                     pref.imask &= ~ (1L << optvalue(0));
  320.                 break;
  321.             case 'O':   /* old tracker type */
  322.                 pref.type = OLD;
  323.                 break;
  324.             case 'N':   /* new tracker type */
  325.                 pref.type = NEW;
  326.                 break;
  327.             case 'v':
  328.                 show = TRUE;
  329.                 break;
  330.             case '=':
  331.                 pref.sync = TRUE;
  332.                 break;
  333.             case 'B':   /* both tracker types */
  334.                 pref.type = BOTH;
  335.                 break;
  336.             case 'r':   /* number of repeats */
  337.                 pref.repeats = optvalue(0);
  338.                 break;
  339.             case 's':   /* speed */
  340.                 pref.speed = optvalue(50);
  341.                 break;
  342.             case 'M':   /* MONO */
  343.                 stereo = 0;
  344.                 break;
  345.             case 'S':   /* STEREO */
  346.                 stereo = 1;
  347.                 break;
  348.             case 'o':   /* oversample */
  349.                 oversample = optvalue(1);
  350.                 break;
  351.             case 'f':   /* frequency */
  352.                 ask_freq = optvalue(0);
  353.                 break;
  354.             case 't':   /* transpose */
  355.                 transpose = optvalue(0);
  356.                 break;
  357.             case 'P':
  358.                 pref.tolerate = 0;
  359.                 break;
  360.             case 'L':
  361.                 pref.tolerate = 2;
  362.                 break;
  363.             case 'm':   /* % of channel mix. 
  364.                          * 0->full stereo, 100->mono */
  365.                 set_mix(optvalue(30));
  366.                 break;
  367.             case 'X':
  368.                 start = optvalue(0);
  369.                 break;
  370.             case 'H':   /* template */
  371.                 fprintf(stderr, "Usage: %s %s", argv[0], USAGE);
  372.                 end_all();
  373.             case 'V':
  374.                 pref.dump_song = TRUE;
  375.                 }
  376. there:
  377.         if (optind < argc)
  378.             {
  379. #ifndef FORKING
  380.             if (run_in_fg())
  381.                 printf("%s:", argv[optind]);
  382. #endif
  383.             switch(pref.type)
  384.                 {
  385.             case BOTH:
  386.                 song = do_read_song(argv[optind], NEW);
  387.                 if (!song && error != NEXT_SONG)
  388.                     song = do_read_song(argv[optind], OLD);
  389.                 break;
  390.             case OLD:
  391.                 song = do_read_song(argv[optind], pref.type);
  392.                 break;
  393.                 /* this is explicitly flagged as a new module,
  394.                  * so we don't need to look for a signature.
  395.                  */
  396.             case NEW:
  397.                 song = do_read_song(argv[optind], NEW_NO_CHECK);
  398.                 break;
  399.                 }
  400.             if (song)
  401.                 is_song[optind] = TRUE;
  402.             else
  403.                 {
  404. #ifndef FORKING
  405.                 puts("not a song");
  406. #endif
  407.                 is_song[optind] = FALSE;
  408.                 continue;
  409.                 }
  410.  
  411. #ifndef FORKING
  412.     printf("\n");
  413. #endif
  414.  
  415.     nonblocking_io();
  416.  
  417. #ifdef FORKING
  418.             if (run_in_fg())
  419.                 printf("\n%s:\n", argv[optind]);
  420.             if (pid)
  421.                 kill(pid, SIGUSR1);
  422.             pid = 0;
  423.             forked = FALSE;
  424. #endif
  425.             if (pref.dump_song)
  426.                 dump_song(song); 
  427.             transpose_song(song, transpose);
  428.             setup_audio(ask_freq, stereo, oversample, pref.sync);
  429.             play_song(song, &pref, start);
  430.             release_song(song);
  431. #ifndef FORKING
  432.             if (run_in_fg())
  433.                 printf("\n");
  434. #endif
  435.         if (error == PREVIOUS_SONG)
  436.             {
  437.             optind --;
  438.             while((optind > 0) && (!is_song[optind]))
  439.                 optind--;
  440.             if (optind == 0)
  441.                 {
  442.                 end_all();
  443.                 exit(0);
  444.                 }
  445.             else
  446.                 goto there;
  447.             }
  448.             }
  449.         }
  450.  
  451.     end_all();
  452.     /* NOT REACHED */
  453.     }
  454.  
  455.  
  456.